using System;
using System.Collections.Generic;

using System.Text;

using Mud.Common.Physical;

namespace Mud.Server.Physical
{

    /// <summary>
    /// Abstract class for events where the source of the event is a creature.
    /// </summary>
    public abstract class CreatureEvent : PhysicalEvent
    {

        /// <summary>
        /// Source of the event.
        /// </summary>
        public Creature Source
        {
            get { return _source; }
            set { _source = value; }
        }
        private Creature _source;


        public CreatureEvent(Creature c) : base(c.Location)
        {
            if (c == null)
                throw new ArgumentNullException("c");
            _source = c;
        }
    }

    /// <summary>
    /// Event which is raised when a creature becomes detectable to some other creature.
    /// </summary>
    public sealed class EventCreatureAppeared : CreatureEvent
    {

        public EventCreatureAppeared(Creature c)
            : base(c)
        {
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }

    }

    /// <summary>
    /// Event which is raised when a creature becomes undetectable to some other creature.
    /// </summary>
    public sealed class EventCreatureDisappeared : CreatureEvent
    {

        public EventCreatureDisappeared(Creature c)
            : base(c)
        {
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }

    }

    /// <summary>
    /// Event which is raised when an object starts to move
    /// </summary>
    public sealed class EventCreatureMoveStarted : CreatureEvent
    {

        /// <summary>
        /// Target position.
        /// </summary>
        public Location TargetPosition
        {
            get { return _target; }
        }
        private Location _target;

        /// <summary>
        /// How long does it take for the movement to finish.
        /// </summary>
        public int Duration
        {
            get { return _duration; }
        }
        private int _duration;

        /// <summary>
        /// Type of movement.
        /// </summary>
        public MovementType MovementType
        {
            get { return _movementType; }
        }
        private MovementType _movementType;


        public EventCreatureMoveStarted(Creature c, Location target, MovementType type, int duration)
            : base(c)
        {
            _target = target;
            _movementType = type;
            _duration = duration;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }
    }

    /// <summary>
    /// Event which is raised when an object ends a move.
    /// </summary>
    public sealed class EventCreatureMoveEnded : CreatureEvent
    {

        /// <summary>
        /// Where the creature moved.
        /// </summary>
        public Location TargetSquare
        {
            get { return _target; }
        }
        private Location _target;

        public EventCreatureMoveEnded(Creature c, Location target)
            : base(c)
        {
            _target = target;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }
    }

    /// <summary>
    /// Event which is raised when an object says something
    /// </summary>
    public sealed class EventCreatureSay : CreatureEvent
    {

        /// <summary>
        /// What is said.
        /// </summary>
        public string Message
        {
            get { return _message; }
        }
        private string _message;

        /// <summary>
        /// Type of communication.
        /// </summary>
        public CommunicationType CommunicationType
        {
            get { return _type; }
        }
        private CommunicationType _type;

        /// <summary>
        /// Target of the communication (can be null).
        /// </summary>
        public Creature Target
        {
            get { return _target; }
        }
        private Creature _target;


        public EventCreatureSay(Creature c, CommunicationType type, string message, Creature target)
            : base(c)
        {
            _message = message;
            _type = type;
            _target = target;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }
    }

    /// <summary>
    /// Event is raised when a creature appears in the area.
    /// </summary>
    public sealed class EventCreatureEnteredArea : CreatureEvent
    {
        /// <summary>
        /// Which area has the creature entered.
        /// </summary>
        public Area Area
        {
            get { return _area; }
        }
        private Area _area;

        /// <summary>
        /// Location where the creature appeared.
        /// </summary>
        public Location Location
        {
            get { return _location; }
        }
        private Location _location;


        public EventCreatureEnteredArea(Creature c, Area area, Location location)
            : base(c)
        {
            _area = area;
            _location = location;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }

    }


    /// <summary>
    /// Event is raised when a creature exits its area.
    /// </summary>
    public sealed class EventCreatureExitedArea : CreatureEvent
    {

        /// <summary>
        /// Which area has the creature exited.
        /// </summary>
        public Area Area
        {
            get { return _area; }
        }
        private Area _area;


        public EventCreatureExitedArea(Creature c, Area area)
            : base(c)
        {
            _area = area;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }

    }


    /// <summary>
    /// Event is raised when a creature turns.
    /// </summary>
    public sealed class EventCreatureTurned : CreatureEvent
    {

        public Orientation Direction
        {
            get { return _direction; }
        }
        private Orientation _direction;


        public EventCreatureTurned(Creature c, Orientation o)
            : base(c)
        {
            _direction = o;
        }

        public override void Send(IPhysicalEventReceiver receiver) { receiver.Receive(this); }

    }
}
